package com.wlsk.license.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.wlsk.license.common.exception.BusinessException;
import com.wlsk.license.common.utils.DataUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Aspect
@Slf4j
@Configuration
public class LogRecordAspect {

    @Pointcut("execution(* com.wlsk.license.controller..*Controller.*(..))")
    public void executeService() {
    }

    @Around("executeService()")
    public Object doAround(ProceedingJoinPoint pjp) {
        try {
            MDC.put("requestId", DataUtil.uuid());
            Long startTime = System.currentTimeMillis();
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            HttpServletRequest request = sra.getRequest();
            String method = request.getMethod();
            String url = request.getRequestURL().toString();
            String body = "";
            Object[] args = pjp.getArgs();

            Stream<?> stream = ArrayUtils.isEmpty(args) ? Stream.empty() : Stream.of(args);
            List<Object> logArgs = stream
                    .filter(arg -> (!(arg instanceof StandardMultipartHttpServletRequest)
                            && !(arg instanceof StandardMultipartHttpServletRequest)
                            && !(arg instanceof HttpServletRequest)
                            && !(arg instanceof HttpServletResponse)
                            && !(arg instanceof ServletRequestDataBinder)
                            && !(arg instanceof org.springframework.web.multipart.MultipartFile || arg instanceof org.springframework.web.multipart.MultipartFile[])
                            && !(arg instanceof org.springframework.core.io.Resource)))
                    .collect(Collectors.toList());
            body = JSON.toJSONString(logArgs);

            Object result = pjp.proceed(); //调用目标方法
            String resultString = JSON.toJSONString(result, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);

            log.info("Http请求参数, url:{}, method:{}, body:{}, 返回值:{}, 耗时:{}ms",
                    url, method, body, resultString, System.currentTimeMillis() - startTime);
            return result;
        } catch (Throwable e) {
            log.error("LogRecordAspect异常:", e);
            if(e instanceof BusinessException){
                throw (BusinessException) e;
            }
        } finally {
            MDC.remove("requestId");
        }
        return null;
    }
}
